package com.zenithmind.chat.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.zenithmind.chat.mapper.ChatMessageMapper;
import com.zenithmind.chat.mapper.ChatMessageReadMapper;
import com.zenithmind.chat.mapper.ChatGroupMemberMapper;
import com.zenithmind.chat.pojo.entity.ChatGroupMember;
import com.zenithmind.chat.pojo.dto.ChatMessageDTO;
import com.zenithmind.chat.pojo.entity.ChatMessage;
import com.zenithmind.chat.pojo.entity.ChatMessageRead;
import com.zenithmind.chat.pojo.query.ChatMessageQuery;
import com.zenithmind.chat.pojo.vo.ChatMessageVO;
import com.zenithmind.chat.pojo.vo.ChatUserVO;
import com.zenithmind.chat.service.ChatMessageService;
import com.zenithmind.common.context.UserContext;
import com.zenithmind.common.exception.BusinessException;
import com.zenithmind.common.result.PageResult;
import com.zenithmind.common.utils.BeanCopyUtils;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.CollectionUtils;
import org.springframework.util.StringUtils;

import java.time.LocalDateTime;
import java.util.List;
import java.util.Objects;
import java.util.stream.Collectors;

/**
 * 聊天消息服务实现类
 * 
 * @author ZenithMind Team
 * @since 2025-01-09
 */
@Slf4j
@Service
@RequiredArgsConstructor
public class ChatMessageServiceImpl extends ServiceImpl<ChatMessageMapper, ChatMessage> implements ChatMessageService {

    private final ChatMessageReadMapper messageReadMapper;
    private final ChatGroupMemberMapper groupMemberMapper;

    @Override
    public PageResult<ChatMessageVO> getMessagePage(ChatMessageQuery query, String userId) {
        Page<ChatMessage> page = query.toPage();

        LambdaQueryWrapper<ChatMessage> wrapper = new LambdaQueryWrapper<>();
        wrapper.eq(StringUtils.hasText(query.getGroupId()), ChatMessage::getGroupId, query.getGroupId())
               .like(StringUtils.hasText(query.getContent()), ChatMessage::getContent, query.getContent())
               .eq(query.getMessageType() != null, ChatMessage::getMessageType, query.getMessageType())
               .eq(query.getStatus() != null, ChatMessage::getStatus, query.getStatus())
               .eq(StringUtils.hasText(query.getSenderId()), ChatMessage::getSenderId, query.getSenderId())
               .orderByDesc(ChatMessage::getSendTime);

        IPage<ChatMessage> result = page(page, wrapper);

        List<ChatMessageVO> voList = result.getRecords().stream()
            .map(message -> convertToVO(message, userId))
            .collect(Collectors.toList());

        return PageResult.of(voList, result.getTotal());
    }

    @Override
    public List<ChatMessageVO> getGroupMessages(String groupId, String userId, String lastMessageId, Integer limit) {
        LambdaQueryWrapper<ChatMessage> wrapper = new LambdaQueryWrapper<>();
        wrapper.eq(ChatMessage::getGroupId, groupId)
                .eq(ChatMessage::getStatus, 1);

        if (StringUtils.hasText(lastMessageId)) {
            wrapper.lt(ChatMessage::getId, lastMessageId);
        }

        wrapper.orderByDesc(ChatMessage::getSendTime);

        if (limit != null && limit > 0) {
            wrapper.last("LIMIT " + limit);
        }

        List<ChatMessage> messages = list(wrapper);
        return messages.stream()
                .map(message -> convertToVO(message, userId))
                .collect(Collectors.toList());
    }

    @Override
    public ChatMessageVO getMessageById(String id, String userId) {
        ChatMessage message = getById(id);
        if (message == null) {
            throw new BusinessException("消息不存在");
        }

        ChatMessageVO messageVO = convertToVO(message, userId);
        
        // 检查当前用户是否已读
        if (StringUtils.hasText(userId)) {
            // TODO: 实现 checkUserReadMessage
            // Boolean isRead = messageReadMapper.checkUserReadMessage(id, userId);
            messageVO.setIsRead(false);
        }
        
        return messageVO;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public String sendMessage(ChatMessageDTO messageDTO, String userId) {
        // 验证参数
        validateMessageDTO(messageDTO);
        
        // 检查发送权限
        if (!checkSendPermission(messageDTO.getGroupId(), userId)) {
            throw new BusinessException("无权限发送消息");
        }
        
        // 创建消息
        ChatMessage message = BeanCopyUtils.copyBean(messageDTO, ChatMessage.class);
        message.setSenderId(userId);
        message.setSenderName(UserContext.getUsername());
        message.setSenderAvatar(""); // TODO: 获取用户头像
        message.setStatus(1); // 正常状态
        message.setSendTime(LocalDateTime.now());
        
        // 处理@提及用户
        if (!CollectionUtils.isEmpty(messageDTO.getMentionUsers())) {
            message.setMentionUsers(String.join(",", messageDTO.getMentionUsers()));
        }
        
        // 处理回复消息
        if (StringUtils.hasText(messageDTO.getReplyToId())) {
            ChatMessage replyToMessage = getById(messageDTO.getReplyToId());
            if (replyToMessage != null) {
                message.setReplyToContent(replyToMessage.getContent());
            }
        }
        
        save(message);
        
        log.info("用户 {} 发送消息到群组 {}: {}", userId, messageDTO.getGroupId(), message.getId());
        return message.getId();
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public Boolean recallMessage(String id, String userId, String reason) {
        ChatMessage message = getById(id);
        if (message == null) {
            throw new BusinessException("消息不存在");
        }
        
        // 检查权限（只能撤回自己的消息或管理员撤回）
        if (!Objects.equals(message.getSenderId(), userId)) {
            // TODO: 检查是否为群组管理员
            throw new BusinessException("无权限撤回该消息");
        }
        
        // 检查时间限制（发送后2分钟内可撤回）
        if (message.getSendTime().isBefore(LocalDateTime.now().minusMinutes(2))) {
            throw new BusinessException("消息发送超过2分钟，无法撤回");
        }
        
        // 更新消息状态
        message.setStatus(2); // 已撤回
        message.setRecallTime(LocalDateTime.now());
        message.setRecallReason(reason);
        updateById(message);
        
        log.info("用户 {} 撤回消息: {}", userId, id);
        return true;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public Boolean deleteMessage(String id, String userId) {
        ChatMessage message = getById(id);
        if (message == null) {
            throw new BusinessException("消息不存在");
        }
        
        // 检查权限（只能删除自己的消息或管理员删除）
        if (!Objects.equals(message.getSenderId(), userId)) {
            // TODO: 检查是否为群组管理员
            throw new BusinessException("无权限删除该消息");
        }
        
        // 软删除
        removeById(id);
        
        log.info("用户 {} 删除消息: {}", userId, id);
        return true;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public Boolean deleteMessagesBatch(List<String> ids, String userId) {
        if (CollectionUtils.isEmpty(ids)) {
            return false;
        }
        
        for (String id : ids) {
            deleteMessage(id, userId);
        }
        
        return true;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public Boolean pinMessage(String id, String userId) {
        ChatMessage message = getById(id);
        if (message == null) {
            throw new BusinessException("消息不存在");
        }
        
        // TODO: 检查是否为群组管理员
        
        message.setIsPinned(1);
        message.setPinTime(LocalDateTime.now());
        updateById(message);
        
        log.info("用户 {} 置顶消息: {}", userId, id);
        return true;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public Boolean unpinMessage(String id, String userId) {
        ChatMessage message = getById(id);
        if (message == null) {
            throw new BusinessException("消息不存在");
        }
        
        // TODO: 检查是否为群组管理员
        
        message.setIsPinned(0);
        message.setPinTime(null);
        updateById(message);
        
        log.info("用户 {} 取消置顶消息: {}", userId, id);
        return true;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public Boolean likeMessage(String id, String userId) {
        // TODO: 实现点赞逻辑
        return true;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public Boolean unlikeMessage(String id, String userId) {
        // TODO: 实现取消点赞逻辑
        return true;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public Boolean markMessagesAsRead(List<String> messageIds, String userId) {
        if (CollectionUtils.isEmpty(messageIds)) {
            return false;
        }
        
        String userName = UserContext.getUsername();
        LocalDateTime readTime = LocalDateTime.now();
        
        // TODO: 实现 batchMarkAsRead
        // Integer count = messageReadMapper.batchMarkAsRead(messageIds, userId, userName, readTime);
        
        log.info("用户 {} 标记 {} 条消息为已读", userId, messageIds.size());
        return true;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public Boolean markGroupMessagesAsRead(String groupId, String userId) {
        String userName = UserContext.getUsername();
        LocalDateTime readTime = LocalDateTime.now();
        
        // TODO: 实现 markGroupMessagesAsRead
        // Integer count = messageReadMapper.markGroupMessagesAsRead(groupId, userId, userName, readTime);
        
        log.info("用户 {} 标记群组 {} 所有消息为已读", userId, groupId);
        return true;
    }

    @Override
    public List<ChatUserVO> getMessageReadUsers(String messageId) {
        // return messageReadMapper.selectMessageReadUsers(messageId);
        return List.of(); // TODO: 实现
    }

    @Override
    public List<ChatUserVO> getMessageUnreadUsers(String messageId) {
        ChatMessage message = getById(messageId);
        if (message == null) {
            throw new BusinessException("消息不存在");
        }
        // return messageReadMapper.selectMessageUnreadUsers(messageId, message.getGroupId());
        return List.of(); // TODO: 实现
    }

    @Override
    public List<ChatMessageVO> searchMessages(String groupId, String keyword, Integer messageType, 
                                            String senderId, String startTime, String endTime, Integer limit) {
        LocalDateTime start = StringUtils.hasText(startTime) ? LocalDateTime.parse(startTime) : null;
        LocalDateTime end = StringUtils.hasText(endTime) ? LocalDateTime.parse(endTime) : null;

        LambdaQueryWrapper<ChatMessage> wrapper = new LambdaQueryWrapper<>();
        wrapper.eq(StringUtils.hasText(groupId), ChatMessage::getGroupId, groupId)
                .like(StringUtils.hasText(keyword), ChatMessage::getContent, keyword)
                .eq(messageType != null, ChatMessage::getMessageType, messageType)
                .eq(StringUtils.hasText(senderId), ChatMessage::getSenderId, senderId)
                .ge(start != null, ChatMessage::getSendTime, start)
                .le(end != null, ChatMessage::getSendTime, end)
                .orderByDesc(ChatMessage::getSendTime);

        if (limit != null && limit > 0) {
            wrapper.last("LIMIT " + limit);
        }

        List<ChatMessage> messages = list(wrapper);
        return messages.stream()
                .map(msg -> convertToVO(msg, null))
                .collect(Collectors.toList());
    }

    @Override
    public List<ChatMessageVO> getPinnedMessages(String groupId) {
        // return baseMapper.selectPinnedMessages(groupId);
        return List.of(); // TODO: 实现
    }

    @Override
    public List<ChatMessageVO> getMentionMessages(String userId, String groupId, Boolean isRead) {
        // return baseMapper.selectMentionMessages(userId, groupId, isRead);
        return List.of(); // TODO: 实现
    }

    @Override
    public Integer getUnreadMessageCount(String groupId, String userId) {
        // LocalDateTime lastReadTime = messageReadMapper.selectUserLastReadTime(groupId, userId);
        // return baseMapper.countUnreadMessages(groupId, userId, lastReadTime);
        return 0; // TODO: 实现
    }

    @Override
    public ChatMessageVO getLatestMessage(String groupId, String userId) {
        LambdaQueryWrapper<ChatMessage> wrapper = new LambdaQueryWrapper<>();
        wrapper.eq(ChatMessage::getGroupId, groupId)
               .eq(ChatMessage::getStatus, 1)
               .orderByDesc(ChatMessage::getSendTime)
               .last("LIMIT 1");

        ChatMessage message = getOne(wrapper);
        return message != null ? convertToVO(message, userId) : null;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public String sendSystemMessage(String groupId, String content, Integer messageType) {
        ChatMessage message = new ChatMessage();
        message.setGroupId(groupId);
        message.setSenderId("system");
        message.setSenderName("系统");
        message.setMessageType(messageType);
        message.setContent(content);
        message.setStatus(1);
        message.setSendTime(LocalDateTime.now());
        
        save(message);
        
        log.info("发送系统消息到群组 {}: {}", groupId, content);
        return message.getId();
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public Boolean forwardMessage(String messageId, List<String> targetGroupIds, String userId) {
        // TODO: 实现转发消息逻辑
        return true;
    }

    @Override
    public Object getMessageStatistics(String groupId, String startTime, String endTime) {
        LambdaQueryWrapper<ChatMessage> wrapper = new LambdaQueryWrapper<>();

        if (StringUtils.hasText(groupId)) {
            wrapper.eq(ChatMessage::getGroupId, groupId);
        }

        if (StringUtils.hasText(startTime)) {
            wrapper.ge(ChatMessage::getSendTime, LocalDateTime.parse(startTime));
        }

        if (StringUtils.hasText(endTime)) {
            wrapper.le(ChatMessage::getSendTime, LocalDateTime.parse(endTime));
        }

        long totalMessages = count(wrapper);

        return new Object() {
            public final Long total = totalMessages;
            public final Long text = 0L;
            public final Long image = 0L;
            public final Long file = 0L;
            public final Long voice = 0L;
            public final Long video = 0L;
        };
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public Integer cleanExpiredMessages(Integer days) {
        LocalDateTime expireTime = LocalDateTime.now().minusDays(days);
        // return baseMapper.cleanExpiredMessages(expireTime);
        return 0; // TODO: 实现
    }

    @Override
    public Boolean checkSendPermission(String groupId, String userId) {
        // 检查用户是否为群组成员
        LambdaQueryWrapper<ChatGroupMember> memberWrapper = new LambdaQueryWrapper<>();
        memberWrapper.eq(ChatGroupMember::getGroupId, groupId)
                     .eq(ChatGroupMember::getUserId, userId)
                     .eq(ChatGroupMember::getStatus, 1);
        
        long memberCount = groupMemberMapper.selectCount(memberWrapper);
        if (memberCount == 0) {
            return false;
        }
        
        // 检查用户是否被禁言
        ChatGroupMember member = groupMemberMapper.selectOne(memberWrapper);
        if (member != null && member.getIsMuted() != null && member.getIsMuted() == 1) {
            // 检查禁言是否过期
            if (member.getMuteEndTime() != null && member.getMuteEndTime().isAfter(LocalDateTime.now())) {
                return false;
            }
        }
        
        return true;
    }

    // 私有方法
    private void validateMessageDTO(ChatMessageDTO messageDTO) {
        if (!StringUtils.hasText(messageDTO.getGroupId())) {
            throw new BusinessException("群组ID不能为空");
        }
        
        if (messageDTO.getMessageType() == null || messageDTO.getMessageType() < 1 || messageDTO.getMessageType() > 8) {
            throw new BusinessException("消息类型无效");
        }
        
        if (messageDTO.getMessageType() == 1 && !StringUtils.hasText(messageDTO.getContent())) {
            throw new BusinessException("文本消息内容不能为空");
        }
    }

    private String getMessageTypeText(Integer type) {
        switch (type) {
            case 1: return "文本消息";
            case 2: return "图片消息";
            case 3: return "文件消息";
            case 4: return "语音消息";
            case 5: return "视频消息";
            case 6: return "系统消息";
            case 7: return "表情消息";
            case 8: return "链接消息";
            default: return "未知消息";
        }
    }

    private String getMessageStatusText(Integer status) {
        switch (status) {
            case 1: return "正常";
            case 2: return "已撤回";
            case 3: return "已删除";
            default: return "未知";
        }
    }

    private ChatMessageVO convertToVO(ChatMessage message, String userId) {
        ChatMessageVO messageVO = BeanCopyUtils.copyBean(message, ChatMessageVO.class);
        
        // 设置消息类型文本
        messageVO.setMessageTypeText(getMessageTypeText(message.getMessageType()));
        messageVO.setStatusText(getMessageStatusText(message.getStatus()));
        
        // 检查是否为当前用户发送
        messageVO.setIsSelf(Objects.equals(message.getSenderId(), userId));
        
        // 检查是否可以撤回（发送后2分钟内且为自己发送的消息）
        boolean canRecall = messageVO.getIsSelf() && 
                           message.getStatus() == 1 && 
                           message.getSendTime().isAfter(LocalDateTime.now().minusMinutes(2));
        messageVO.setCanRecall(canRecall);
        
        return messageVO;
    }
}
